/*

* Copyright (c) 2007, National University of Singapore (NUS)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without 
* modification, are permitted provided that the following conditions 
* are met:
*
*   * Redistributions of source code must retain the above copyright notice, 
*     this list of conditions,the authors and the following disclaimer.
*   * Redistributions in binary form must reproduce the above copyright notice,
*     this list of conditions,the authors and the following disclaimer in
*     the documentation and/or other materials provided with the distribution.
*   * Neither the name of the university nor the names of its 
*     contributors may be used to endorse or promote products derived from 
*     this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
* POSSIBILITY OF SUCH DAMAGE.
*
* Author: Wenwei Xue (dcsxw@nus.edu.sg)
* 
*/
package psg.servicemanager;
import java.net.*;
import java.io.*;

/**
 * This class implements a Client Socket that is responsible for a specific 
 * event subscription from a caller.
 */
public class EventClientSocket extends Thread {
	
	Socket socket;
	
	BufferedReader br;
	
	PrintWriter pw;	
	
	boolean isUnsubscribed = false;
	
	long SLEEP_INTERVAL = 1000; // unit: millisecond
	
	ContextDataServices cds;
	
	ContextAttribute ca = null;
	
	int eventID = -1;
	
	boolean isNotified = true;  // whether the caller has been notified for a new event occurrence
	
	String oldValue = null;	// old value for the context attribute (for special event: getContextChange)	
	
	EventSubscription es = null;
	
	EventClientSocket(Socket socket, ContextDataServices cds) {
		
		this.socket = socket;
		
		try {
			br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
			pw = new PrintWriter(socket.getOutputStream());
			
			String line = br.readLine().trim();
			//System.out.println("Testing: "+line);					
			int i;
			
			for (i=0;i<cds.ess.subcribedEvents.size();i++) {
				es = (EventSubscription)cds.ess.subcribedEvents.elementAt(i);
				if (line.equals(String.valueOf(es.id)))
					break;
			}
			
			if (i==cds.ess.subcribedEvents.size())
			{
				pw.println("Invalid socket connection!");
				pw.flush();
				
				isUnsubscribed = true;
				
				br.close();
				pw.close();
				socket.close();
				
				return;
			}					
				
			this.cds = cds;			
			
			ca = cds.cd[es.domainID].contextAttrs[es.nameID];
			
			for (i=0;i<ContextAttribute.eventNames.length;i++)
	    		if (ca.name.toLowerCase().equals(ContextAttribute.eventNames[i].toLowerCase()))
	    		{
	    			eventID = i;
	    			break;
	    		}	    	
	    	if (eventID==-1) {
	    		eventID = 2;	// special event: getContextChange
	    		oldValue = ca.value;
	    	}
	    	
	    	es.ecs = this;
					
			//cds.psg.PSComboBox3.removeAllItems();				
			//String subs [] = cds.psg.getSubscribedEvents((String)cds.psg.PSComboBox2.getSelectedItem());
						
			//for (i=0;i<subs.length;i++)
				//cds.psg.PSComboBox3.addItem(subs[i]);

			
		}
		catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public void run () {
		
		while (!isUnsubscribed) {	     	  		
	    	
	    	switch (eventID) {
	    	   case 0: isVacantDetection(ca); break;
	    	   case 1: sendAdvertisement(ca); break;
	    	   case 2: getContextChange(ca); break;
	    	   default: 	
	    	}	    
	    	
	    	try {Thread.currentThread().sleep(SLEEP_INTERVAL);}
	    	catch (Exception e) {e.printStackTrace();}	    	
	    }
	    
	    terminate();
	    
	}  // run
	
	public void terminate() {
		
		try {
	    	br.close();
	    	pw.close();
	    	socket.close();
	    }
	    catch (Exception e) {e.printStackTrace();}
	    
	}
	
	private void isVacantDetection(ContextAttribute ca) {
		
		String notifyMSG = "There is no meeting in the conference room now.";
		
		try {
			if (ca.value.equals("true") && !isNotified) {
				pw.println(notifyMSG);
				pw.flush();
				isNotified = true;
				if (cds.isAllNotified(eventID))
					ca.value = "false";				
			}
		}
		catch (Exception e) {
			e.printStackTrace();
		}	
		
	} // isVacantDetection
	
	private void sendAdvertisement(ContextAttribute ca) {
		
		String ADVERTISEMENT_URL = "http://shopping.ip.mysoc.net/advertisement.htm";	
				
		try {
			if (ca.value.equals("true") && !isNotified) {				
				pw.println(ADVERTISEMENT_URL);
				pw.flush();
				isNotified = true;
				if (cds.isAllNotified(eventID))
					ca.value = "false";				
			}
		}
		catch (Exception e) {
			e.printStackTrace();
		}		
		
	}  // sendAdvertisement
	
	public void getContextChange(ContextAttribute ca) {
		
		try {
			if (!ca.value.equals(oldValue)) {				
				pw.println(ca.value);				
				pw.flush();			
				oldValue = ca.value;			
			}
		}
		catch (Exception e) {
			e.printStackTrace();
		}		
		
	}	// getContextChange
}